import { HttpException, HttpStatus, Injectable, OnApplicationBootstrap } from "@nestjs/common";
import { CreateUserDto } from "./dto/create-user.dto";
import { UpdateUserDto } from "./dto/update-user.dto";
import { Users } from "./entities/user.entity";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { WeChatUserInfo } from "../auth/auth.interface";
import { QueryUserDto } from "./dto/find-user.dto";
import { compareSync } from "bcryptjs";

@Injectable()
export class UsersService implements OnApplicationBootstrap {
	constructor(
		@InjectRepository(Users)
		private userRepository: Repository<Users>
	) {}
	async onApplicationBootstrap() {
		const adminUser = await this.userRepository.findOne({
			where: {
				account: "1624362469"
			}
		});
		if (!adminUser) {
			const data = new CreateUserDto();
			Object.assign(data, {
				account: "1624362469",
				nickname: "陶奇林",
				password: "147258369TQLtql",
				role: "root"
			});
			await this.create(data);
		}
	}
	async create(createUserDto: CreateUserDto) {
		// return 'This action adds a new user';
		const { account } = createUserDto;

		const existUser = await this.userRepository.findOne({
			where: { account }
		});
		if (existUser) {
			throw new HttpException("用户名已存在", HttpStatus.BAD_REQUEST);
		}

		const newUser = await this.userRepository.create(createUserDto);
		return await this.userRepository.save(newUser);
	}

	async registerByWeChat(userInfo: WeChatUserInfo) {
		const { nickname, openid, headimgurl } = userInfo;
		const newUser = await this.userRepository.create({
			nickname,
			openid,
			avatar: headimgurl
		});
		return await this.userRepository.save(newUser);
	}

	async findByOpenid(openid: string) {
		return await this.userRepository.findOne({ where: { openid } });
	}

	async findAll(query?: QueryUserDto) {
		const { pageNum = 1, pageSize = 10, sortBy, role, ...params } = query;
		const qb = this.userRepository.createQueryBuilder("user");
		if (sortBy) {
			const sortByObject = JSON.parse(sortBy);
			Object.keys(sortBy).forEach((key) => qb.orderBy(`user.${key}`, sortByObject[key]));
		}
		if (role) qb.andWhere(`post.role = :role`, { role: role });
		if (params) {
			Object.keys(params).forEach((key) => {
				if (params[key]) qb.andWhere(`post.${key} = :${key}`, { [key]: params[key] });
			});
		}
		const count = await qb.getCount();
		qb.take(pageSize);
		qb.skip(pageSize * (pageNum - 1));
		const users = await qb.getMany();
		return { list: users, count: count };
	}

	async findOne(id: string) {
		return await this.userRepository.findOneBy({ id: id });
	}

	async update(id: string, updateUserDto: UpdateUserDto) {
		const existUser = await this.userRepository.findOneBy({ id: id });
		if (!existUser) {
			throw new HttpException(`id为${id}的用户不存在`, HttpStatus.FORBIDDEN);
		}
		const userToUpdate = this.userRepository.merge(existUser, updateUserDto);
		return await this.userRepository.save(userToUpdate);
	}

	async remove(id: string) {
		const existUser = await this.userRepository.findOneBy({ id: id });
		if (!existUser) {
			throw new HttpException(`id为${id}的用户不存在`, HttpStatus.FORBIDDEN);
		}
		return await this.userRepository.remove(existUser);
	}

	/**
	 * 密码重置
	 * @param id
	 * @returns
	 */
	async resetPassword(id: string) {
		const existUser = await this.userRepository.findOneBy({ id: id });
		if (!existUser) {
			throw new HttpException(`id为${id}的用户不存在`, HttpStatus.FORBIDDEN);
		}
		const userToUpdate = this.userRepository.merge(existUser, {
			password: "123456"
		});
		return await this.userRepository.save(userToUpdate);
	}

	/**
	 * 修改用户密码
	 * @param updateUserId 修改对象
	 * @param oldPassword 旧密码
	 * @param newPassword 新密码
	 */
	async updatePassword(updateUserId: string, oldPassword: string, newPassword: string) {
		const existUser = await this.userRepository
			.createQueryBuilder("users")
			.addSelect("users.password")
			.where("users.id=:id", { id: updateUserId })
			.getOne();
		if (!existUser) {
			throw new HttpException("用户不存在！", HttpStatus.FORBIDDEN);
		}

		if (!compareSync(oldPassword, existUser.password)) {
			throw new HttpException("旧密码密码错误！", HttpStatus.FORBIDDEN);
		}

		const userToUpdate = this.userRepository.merge(existUser, {
			password: newPassword
		});
		return await this.userRepository.save(userToUpdate);
	}
}
